/*
 * smartAligned2DArray.h
 *
 *  Created on: 2011-09-21
 *      Author: pawel
 */

#ifndef SMARTALIGNED2DARRAY_H_
#define SMARTALIGNED2DARRAY_H_
#include<malloc.h>
#include<string.h>
/*
 * use this template only for basic types int,float itp
 * it does not call class constructors
 */
template<class T>
class smartAligned2DArray{
private:
	T **array;
	size_t rows;
	size_t cols;
	size_t ncols;
	size_t boundary;
public:
	smartAligned2DArray(size_t rows,size_t cols,size_t boundary);
	~smartAligned2DArray();
	T** getPtr();
	void release();
};

template<class T>
smartAligned2DArray<T>::smartAligned2DArray(size_t rows,size_t cols,size_t boundary)
:rows(rows),cols(cols),boundary(boundary)
{
	array =  NULL;
	ncols = boundary*(cols*sizeof(T)/boundary +1);
	try{
		array = (T**)malloc(rows*sizeof(T*));
		if(array == NULL) throw std::bad_alloc();
//		for(size_t i=0;i<rows;i++){
//				array[i] = NULL;
//		}
		memset(array,NULL,rows*sizeof(T*));
		for(size_t i=0;i<rows;i++){
			array[i] = (T*)memalign(boundary,ncols);
			memset(array[i],NULL,ncols);
			if(array[i] == NULL) throw std::bad_alloc();
		}
	}catch(std::bad_alloc& e){
		if(array !=NULL){
				for(size_t i=0;i<rows;i++){
					if(array[i]!=NULL){
						free(array[i]);
						array[i]=NULL;
					}
				}
				free( array);
					array= NULL;
			}
		throw;

	}
}

template<class T>
smartAligned2DArray<T>::~smartAligned2DArray(){
	if(array !=NULL){
			for(size_t i=0;i<rows;i++){
				if(array[i]!=NULL){
					free(array[i]);
					array[i]=NULL;
				}
			}
			free( array);
				array= NULL;
		}
}

template <class T>
T** smartAligned2DArray<T>::getPtr(){
	return array;
}
template <class T>
void smartAligned2DArray<T>::release(){

			array = NULL;
}


#endif /* SMARTALIGNED2DARRAY_H_ */
